
#include <avr/io.h>
#include <avr/interrupt.h>

#include <inttypes.h>
#include <util/delay.h>
#include <util/crc16.h>


#include "spi.h"
#include "utils.h"
#include "tickcount.h"
#include "error.h"


#if defined (__AVR_ATmega8__)

#include "uart.h"

	#define RF12_RST_BIT	5	
	#define RF12_RST_PORT	PORTD
	#define RF12_RST_DDR	DDRD

	#define RF12_nIRQ_BIT	2
	#define RF12_nIRQ_PIN	PIND
	#define RF12_nIRQ_DDR	DDRD


#elif defined (__AVR_ATmega16__)

	#define RF12_RST_BIT	0	
	#define RF12_RST_PORT	PORTD
	#define RF12_RST_DDR	DDRD

	#define RF12_nIRQ_BIT	2
	#define RF12_nIRQ_PIN	PIND
	#define RF12_nIRQ_DDR	DDRD

	#define RF12_VDI_BIT	2
	#define RF12_VDI_PORT	PORTB
	#define RF12_VDI_DDR	DDRB

#endif




#define RF12_TIME_OUT_mS 5
#define RF12_REPLY_TIME_OUT_mS 50
#define RFM12_MAX_DATA_PACKET_SIZE 150 /* obsolute maximum: 250 */
#define CRC_INIT_VALUE 0xFFFF


unsigned char TreansmitMode=0;
uint16_t TimeOut_TC;





void RFM12B_FIFOReset() 
{
	SpiDriver_Transaction(0xCA81);
	SpiDriver_Transaction(0xCA83);
}

void RF12_Reset()
{	
		_delay_ms(500);
		RF12_RST_PORT &= ~(1 << RF12_RST_BIT);	// set chip reset to low (device is in reset)
		_delay_ms(500);
		RF12_RST_PORT  |= (1 << RF12_RST_BIT);	// set chip reset to hi (device is in normal work)	
		_delay_ms(500);
}



void RF12_Init(void)
{
	RF12_RST_DDR   |=  (1 << RF12_RST_BIT);		// set port D, device reset to output
	RF12_nIRQ_DDR  &= ~(1 << RF12_nIRQ_BIT);	// set port D, device nIRQ to input

	#if defined (__AVR_ATmega16__)
		RF12_VDI_DDR   &= ~(1 << RF12_VDI_BIT);		// set port B, device VDI to input
	#endif

	RF12_Reset();

	SpiDriver_Transaction(0x80E7); //EL,EF,868band,12.0pF
	SpiDriver_Transaction(0x8239); //er,!ebb,ET,ES,EX,!eb,!ew,DC (bug was here)
	SpiDriver_Transaction(0xA640); //freq select
	SpiDriver_Transaction(0xC610); //20283kbps
	SpiDriver_Transaction(0x9480); //VDI,FAST,200kHz,0dBm,-103dBm
	SpiDriver_Transaction(0xC2AC); //AL,!ml,DIG,DQD4
	SpiDriver_Transaction(0xCA81); //FIFO8,SYNC,!ff,DR (FIFO level = 8)
	SpiDriver_Transaction(0xCED4); //SYNC=2DD4;
	SpiDriver_Transaction(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	SpiDriver_Transaction(0x9850); //!mp,90kHz,MAX OUT
	SpiDriver_Transaction(0xCC77); //!OB1,!OB0, LPX,!ddy,DDIT,BW0
	SpiDriver_Transaction(0xE000); //NOT USE
	SpiDriver_Transaction(0xC800); //NOT USE
	SpiDriver_Transaction(0xC040); //1.66MHz,2.2V


	RFM12B_FIFOReset();
}





unsigned char RF12_GetnIRQPinState(void)
{
	if(RF12_nIRQ_PIN&(1<<RF12_nIRQ_BIT)) return 1; else return 0;
}



void RFM12B_SetTransmitMode(void)
{
	_delay_us(10);
	SpiDriver_Transaction(0x8239);
	RFM12B_FIFOReset();
	TreansmitMode=1;
	_delay_us(100);
}


void RFM12B_SetReceiveMode(void)
{
	_delay_us(10);
	SpiDriver_Transaction(0x8298);
	RFM12B_FIFOReset();
	TreansmitMode=0;
	_delay_us(100);
}

  
unsigned char RFM12B_TransmitByte(unsigned char byte_to_send)
{

	TimeOut_TC=GetTickCount();

	while(RF12_GetnIRQPinState())
	{
		if(GetTickSince(TimeOut_TC)>RF12_TIME_OUT_mS)
		{
			SetError(TRANSMIT_TIMEOUT);
			return 0;
		}
	}

	SpiDriver_Transaction(0xB800 + byte_to_send);

	return 1;
}


unsigned char RFM12B_ReadByte(char *readed_byte)
{

	if(RF12_GetnIRQPinState())
	{
			return 0;
	}
	
	SpiDriver_Transaction(0x0000);
	*readed_byte = (SpiDriver_Transaction(0xB000) & 0x00FF);	
		
return 1;
}






unsigned char RFM12B_WritePacket(unsigned char *packet, int len)
{
	static uint16_t crc;
	crc=CRC_INIT_VALUE;
	static unsigned char switch_to_receive;



	if(TreansmitMode==0) 
	{
      RFM12B_SetTransmitMode();
	  switch_to_receive=1;
	} else
	{
		switch_to_receive=0;
	}

	SpiDriver_Transaction(0x0000);


	RFM12B_TransmitByte(0xAA); // PREAMBLE
	RFM12B_TransmitByte(0xAA);
	RFM12B_TransmitByte(0xAA);
	RFM12B_TransmitByte(0x2D); // SYNC FOR RFM12 FIFO
	RFM12B_TransmitByte(0xD4);
	RFM12B_TransmitByte('['); // DATA PACKET START

	// Transmit data
	for(unsigned char i=0; i<len; i++) 
	{
		crc=_crc16_update(crc,packet[i]);
		RFM12B_TransmitByte(ToHex(packet[i]>>4));
		RFM12B_TransmitByte(ToHex(packet[i]));
	}

	// Add checksum (always last 4 char)

	RFM12B_TransmitByte(ToHex((char)(crc>>12)&0xF));
	RFM12B_TransmitByte(ToHex((char)(crc>>8)&0xF));
	RFM12B_TransmitByte(ToHex((char)(crc>>4)&0xF));
	RFM12B_TransmitByte(ToHex((char)(crc>>0)&0xF));

	RFM12B_TransmitByte(']'); // DATA PACKET STOP
	RFM12B_TransmitByte(0xAA); // DUMMY BYTES
	RFM12B_TransmitByte(0xAA);
	RFM12B_TransmitByte(0xAA);

	if(switch_to_receive==1) 
	{
		/* wait for transmision completed */
		TimeOut_TC=GetTickCount();

		while(RF12_GetnIRQPinState())
		{
			if(GetTickSince(TimeOut_TC)>RF12_TIME_OUT_mS)
			{
				SetError(TRANSMIT_TIMEOUT);
				break;
			}
		}

      RFM12B_SetReceiveMode();
	}


return 1;	
}


#define PARSER_WAIT_FOR_BEGIN 0
#define PARSER_WAIT_FOR_FIRST_CHAR_PART_OR_END 1
#define PARSER_WAIT_FOR_NEXT_CHAR 2

unsigned char ReceivedPacket[RFM12_MAX_DATA_PACKET_SIZE];
unsigned char CurrentMarkerPosition=0;
unsigned char ParserState=PARSER_WAIT_FOR_BEGIN;


/*return values: 0 - no data, 1 - processing data, 2 - packed received*/

unsigned char RFM12B_ReadPacket(unsigned char **packet, unsigned char *len)
{
	static char CurrendReceived;
	


	if(len!=0) *len=0;

		if(TreansmitMode!=0) return 0;

		if((CurrentMarkerPosition+1)>=RFM12_MAX_DATA_PACKET_SIZE) /* data too long - reset parser to initial state */
		{
			SetError(PARSER_RECEIVE_BUFOR_OVERFLOW);
			CurrentMarkerPosition=0;
			ParserState=PARSER_WAIT_FOR_BEGIN;
			RFM12B_FIFOReset();
		}

		if( RFM12B_ReadByte(&CurrendReceived)==0 ) 	return 0;


		if(ParserState==PARSER_WAIT_FOR_BEGIN)
		{
			if(CurrendReceived=='[')
			{
				ParserState=PARSER_WAIT_FOR_FIRST_CHAR_PART_OR_END;
				return 1;
			}
		}

		if(ParserState==PARSER_WAIT_FOR_FIRST_CHAR_PART_OR_END)
		{
			if(CurrendReceived==']')
			{
				/* end of data */
				/* check check sum*/
				static uint16_t packet_crc,received_crc;
				unsigned char crc_item;
				packet_crc=CRC_INIT_VALUE;

				for(crc_item=0;crc_item<(CurrentMarkerPosition-2);crc_item++)
				{
						packet_crc=_crc16_update(packet_crc,ReceivedPacket[crc_item]);
				}

				received_crc=(ReceivedPacket[CurrentMarkerPosition-2]<<8)|(ReceivedPacket[CurrentMarkerPosition-1]);
				
				/* --- */
				if(len!=0) *len=CurrentMarkerPosition-2;
				CurrentMarkerPosition=0;
				ParserState=PARSER_WAIT_FOR_BEGIN;
				RFM12B_FIFOReset();

				if(received_crc==packet_crc) 
				{ 
					*packet=&ReceivedPacket;
					return 2; 
				}
					else
				{
			     SetError(RECEIVED_PACKET_CRC_ERROR);
				 return 0;
				}
			}

			ReceivedPacket[CurrentMarkerPosition]=(Hex2Bin(CurrendReceived)<<4);
			ParserState=PARSER_WAIT_FOR_NEXT_CHAR;
			return 1;

		}

		if(ParserState==PARSER_WAIT_FOR_NEXT_CHAR)
		{
			ReceivedPacket[CurrentMarkerPosition]|=(Hex2Bin(CurrendReceived)&0x0F);
			ParserState=PARSER_WAIT_FOR_FIRST_CHAR_PART_OR_END;
			CurrentMarkerPosition++;
			
			return 1;
		}


		return 0;		
}



unsigned char RFM12B_SendPacketAndWaitForReply(unsigned char *packet_to_send,unsigned char packet_to_send_len, unsigned char **received_packet,unsigned char *received_packet_len)
{
	unsigned char ret;
	ret=1;
	static unsigned char restore_transmit_mode;

	if(TreansmitMode==1) 
	{
		RFM12B_SetReceiveMode();
		restore_transmit_mode=1;
	} else
	{
		restore_transmit_mode=0;
	}

	
	RFM12B_WritePacket(packet_to_send,packet_to_send_len);

	TimeOut_TC=GetTickCount();

	while(RFM12B_ReadPacket(received_packet,received_packet_len)!=2)
	{
			if(GetTickSince(TimeOut_TC)>RF12_REPLY_TIME_OUT_mS)
			{
			    SetError(REPLY_TIMEOUT);
				ret=0;
				break;
			}
	}


	if(restore_transmit_mode==1) RFM12B_SetTransmitMode();

	return ret;
}





